/**
 *
 * @description:
 * @author: junyong.hong
 * @createTime: 2019/9/25
 * @version: 1.0.0.0
 * @history:
 *    1、
 *    2、
 *
 */
const jsonwebtoken = require('jsonwebtoken')
const User = require('../models/users')
const Question = require('../models/questions')
const Answer = require('../models/answers')
const { secret } = require('../config')

class UserCtl {
    // 获取用户列表
    async find(ctx) {
        const { per_page = 10 } = ctx.query

        // 当前第几页
        const page = Math.max(ctx.query.page * 1, 1) - 1
        // 每页有多少项
        const perPage = Math.max(per_page * 1, 1)

        // limit(10)只返回10项
        // skip(10)跳过前10项
        // limit(10).skip(10) 返回第二页，跳过前10条数据

        // page 1
        // perPage 10
        ctx.body = await User.find().find({ name: new RegExp(ctx.query.q) })
                                    .limit(perPage).skip(page * perPage)
    }

    // 获取特定用户
    async findById(ctx) {
        const { fields = '' } = ctx.query
        // 访问路径：?fields=locations;business
        // filter(f => f)代表f必须存在
        // .join('')数组拼到一起
        // .join(' ')空格隔开
        const selectFields = fields.split(';').filter(f => f).map(f => ' +' + f).join('')

        const populateStr = fields.split(';').filter(f => f).map(f => {
            if (f === 'employments') {
                return 'employments.job educations.school'
            }
            if (f === 'education') {
                return 'educations.school education.major'
            }
            return f
        }).join(' ')

        // populate查询id关联的相关信息
        // .populate('following locations business employments.company employments.job educations.school education.major')
        const user = await User.findById(ctx.params.id).select(selectFields)
            .populate(populateStr)

        if (!user) {
            ctx.throw(404, '用户不存在')
        }
        ctx.body = user
    }

    // 创建用户
    async create(ctx) {
        // 校验
        ctx.verifyParams({
            name: {
                type: 'string',
                required: true
            },
            password: {
                type: 'string',
                required: true
            }
        })

        // 判断用户是否已经存在
        const { name } = ctx.request.body
        const repeatedUser = await User.findOne({ name })
        if (repeatedUser) {
            ctx.throw(409, '用户已经占用')
        }

        const user = await new User(ctx.request.body).save()
        ctx.body = user
    }

    // 修改用户
    async update(ctx) {
        // 校验
        ctx.verifyParams({
            name: {
                type: 'string',
                required: false
            },
            password: {
                type: 'string',
                required: false
            },
            avatar_url: {
                type: 'string',
                required: false
            },
            gender: {
                type: 'string',
                required: false
            },
            headline: {
                type: 'string',
                required: false
            },
            locations: {
                // 数组
                type: 'array',
                // 数组里每一项都是字符串
                itemType: 'string',
                required: false
            },
            business: {
                type: 'string',
                required: false
            },
            employments: {
                // 数组
                type: 'array',
                // 数组里每一项都是对象
                itemType: 'object',
                required: false
            },
            educations: {
                // 数组
                type: 'array',
                // 数组里每一项都是对象
                itemType: 'object',
                required: false
            }
        })

        const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
        if (!user) {
            ctx.throw(404, '用户不存在')
        }
        ctx.body = user
    }

    // 删除用户
    async delete(ctx) {
        const user = await User.findByIdAndRemove(ctx.params.id)
        if (!user) {
            ctx.throw(404, '用户不存在')
        }
        ctx.body = user
    }

    // 登录
    async login(ctx) {
        // 校验
        ctx.verifyParams({
            name: {
                type: 'string',
                required: true
            },
            password: {
                type: 'string',
                required: true
            }
        })

        const user = await User.findOne(ctx.request.body)
        if (!user) {
            ctx.throw(401, '用户名或密码不正确')
        }

        // 设置密钥
        const { _id, name } = user
        const token = jsonwebtoken.sign({ _id, name }, secret, { expiresIn: '1d' })

        ctx.body = { token }
    }

    // 判断是否当前登录的用户
    async checkOwner(ctx, next) {
        // jwt会把用户信息方在ctx.state.user中
        if (ctx.params.id !== ctx.state.user._id) {
            ctx.throw(403, '没有权限')
        }
        await next()
    }

    // 获取关注者与粉丝
    async listFollowing(ctx, next) {
        // select('+following')才能查到following字段
        // populate('following')如果没加，只会返回关注者id
        const user = await User.findById(ctx.params.id).select('+following').populate('following')
        if (!user) {
            ctx.throw(404)
        }
        ctx.body = user.following
    }

    // 关注某人
    async follow(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+following')

        // mongoose map批量转数组
        if (!me.following.map(id => id.toString()).includes(ctx.params.id)) {
            me.following.push(ctx.params.id)
            me.save()
        }
        ctx.status = 204

    }

    // 取消关注
    async unfollow(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+following')
        const index = me.following.map(id => id.toString()).indexOf(ctx.params.id)

        if (index > -1) {
            me.following.splice(index, 1)
            me.save()
        }
        ctx.status = 204
    }

    // 获取某个用户的粉丝列表
    async listFollowers(ctx) {
        const users = await User.find({ following: ctx.params.id })
        ctx.body = users
    }

    // 校验用户存在与否（判断id是否存在）
    async checkUserExist(ctx, next) {
        const user = await User.findById(ctx.params.id)
        if (!user) {
            ctx.throw(404, '用户不存在')
        }
        await next()
    }

    // 关注话题
    async followTopic(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+followingTopics')

        // mongoose map批量转数组
        if (!me.followingTopics.map(id => id.toString()).includes(ctx.params.id)) {
            me.followingTopics.push(ctx.params.id)
            me.save()
        }
        ctx.status = 204

    }

    // 取消关注话题
    async unfollowTopic(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+followingTopics')
        const index = me.followingTopics.map(id => id.toString()).indexOf(ctx.params.id)

        if (index > -1) {
            me.followingTopics.splice(index, 1)
            me.save()
        }
        ctx.status = 204
    }

    // 获取某个用户的话题列表
    async listFollowersTopics(ctx) {
        const user = await User.findById(ctx.params.id).select('+followingTopics').populate('followingTopics');
        if (!user) { ctx.throw(404, '话题不存在'); }
        ctx.body = user.followingTopics;
    }

    // 用户的问题列表
    async listQuestions(ctx) {
        const questions = await Question.find({ questioner: ctx.params.id });
        ctx.body = questions;
    }

    // 获取某个用户赞的答案
    async listLikingAnswers(ctx) {
        const user = await User.findById(ctx.params.id).select('+likingAnswers').populate('likingAnswers');
        if (!user) { ctx.throw(404, '用户不存在'); }
        ctx.body = user.likingAnswers;
    }

    // 赞答案
    async likeAnswer(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+likingAnswers');
        if (!me.likingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
            me.likingAnswers.push(ctx.params.id);
            me.save();
            // $inc增加1
            await Answer.findByIdAndUpdate(ctx.params.id, { $inc: { voteCount: 1 } });
        }
        ctx.status = 204;
        await next();
    }

    // 取消赞答案
    async unlikeAnswer(ctx) {
        const me = await User.findById(ctx.state.user._id).select('+likingAnswers');
        const index = me.likingAnswers.map(id => id.toString()).indexOf(ctx.params.id);
        if (index > -1) {
            me.likingAnswers.splice(index, 1);
            me.save();
            // $inc减1
            await Answer.findByIdAndUpdate(ctx.params.id, { $inc: { voteCount: -1 } });
        }
        ctx.status = 204;
    }

    // 获取某个用户踩的答案
    async listDislikingAnswers(ctx) {
        const user = await User.findById(ctx.params.id).select('+dislikingAnswers').populate('dislikingAnswers');
        if (!user) { ctx.throw(404, '用户不存在'); }
        ctx.body = user.dislikingAnswers;
    }

    // 踩答案
    async dislikeAnswer(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+dislikingAnswers');
        if (!me.dislikingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
            me.dislikingAnswers.push(ctx.params.id);
            me.save();
        }
        ctx.status = 204;
        await next();
    }

    // 取消踩答案
    async undislikeAnswer(ctx) {
        const me = await User.findById(ctx.state.user._id).select('+dislikingAnswers');
        const index = me.dislikingAnswers.map(id => id.toString()).indexOf(ctx.params.id);
        if (index > -1) {
            me.dislikingAnswers.splice(index, 1);
            me.save();
        }
        ctx.status = 204;
    }

    // 列出收藏的答案
    async listCollectingAnswers(ctx) {
        const user = await User.findById(ctx.params.id).select('+collectingAnswers').populate('collectingAnswers');
        if (!user) { ctx.throw(404, '用户不存在'); }
        ctx.body = user.collectingAnswers;
    }

    // 收藏答案
    async collectAnswer(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select('+collectingAnswers');
        if (!me.collectingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
            me.collectingAnswers.push(ctx.params.id);
            me.save();
        }
        ctx.status = 204;
        await next();
    }

    // 取消收藏答案
    async uncollectAnswer(ctx) {
        const me = await User.findById(ctx.state.user._id).select('+collectingAnswers');
        const index = me.collectingAnswers.map(id => id.toString()).indexOf(ctx.params.id);
        if (index > -1) {
            me.collectingAnswers.splice(index, 1);
            me.save();
        }
        ctx.status = 204;
    }
}

module.exports = new UserCtl()